import java.io.*;
import java.net.*;
import java.util.*;
import java.sql.*;


public class Client{

    private Socket socket;
    private BufferedWriter writer;
    private BufferedReader input;
    private Scanner scanner;
    private Encryption enc;
    private String username;
    private UserServer us;
    private int port;

    public Client(){

        try{
            scanner = new Scanner(System.in);
			long ini = System.nanoTime();
            socket = new Socket("frontend", 8080);
            long fim = System.nanoTime();
            System.out.println("Conectado. Tempo de conexao com o servidor: "+ (fim-ini));

            writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            input = new BufferedReader(new InputStreamReader(socket.getInputStream()));


            enc = new Encryption();

            setMyName();
            
            us = new UserServer(port);
            Thread t1 = new Thread(us);
            t1.start();
            
            getMyName();
            getMyPort();
            SendMessage();

        }catch(Exception e){ System.out.println(e.getMessage());}


    }

    public void Escrever(String msgm){

        try{
            msgm = enc.encrypt(msgm);
            writer.write(msgm);
            writer.newLine();
            writer.flush();
        }catch(Exception e){e.printStackTrace();}

    }

    public void getMyPort(){
        Escrever("MyPort_"+port);
    }


    public void setMyName(){
        try{
            BufferedReader input_file = new BufferedReader(new FileReader("MyName"));
            username = input_file.readLine();
            String[] parts = username.split("_");
            username = parts[0];
            port = Integer.parseInt(parts[1]); 
        }catch(Exception e){e.printStackTrace();}
    }

    public void getMyName(){
        try{
            String user_send = enc.encrypt(username);
            writer.write(user_send);
            writer.newLine();
            writer.flush();
        }catch(Exception e){e.printStackTrace();}
    }

    public void SendMessage(){

        String msgm = "";
        int op=0;

        while(op!=7){   

            try{

                System.out.println("\n1 --> Meus arquivos");
                System.out.println("2 --> Arquivos disponiveis para download");
                System.out.println("3 --> Baixar arquivo");
                System.out.println("4 --> Adicionar arquivo ao compartilhamento");
                System.out.println("5 --> Atualizar lista de arquivos");
                System.out.println("6 --> Remover arquivo da lista de arquivos");
                System.out.println("7 --> Sair");

                op = scanner.nextInt();

                if(op==2){
                    /* pedir para o webserver os arquivos que eu sou dono */
                    msgm = "AllFiles";
                    msgm = enc.encrypt(msgm);
                    writer.write(msgm);
                    writer.newLine();
                    writer.flush();

                    msgm = input.readLine();
                    msgm = enc.decrypt(msgm);

                    String parts[];

                    parts = msgm.split("_");

                    System.out.println("All files for download:");
                    for(int i=0;i<parts.length;i++){
                        System.out.println(parts[i]);
                    }

                }
                else if(op==1){
                    /* pedir para o webserver todos os arquivos */
                    msgm = "MyFiles";
                    msgm = enc.encrypt(msgm);
                    writer.write(msgm);
                    writer.newLine();
                    writer.flush();

                    msgm = input.readLine();
                    msgm = enc.decrypt(msgm);

                    String parts[];

                    parts = msgm.split("_");

                    System.out.println("Meus arquivos:");
                    for(int i=0;i<parts.length;i++){
                        System.out.println(parts[i]);
                    }

                }
                else if(op==3){

                    /* Usuario  quer baixar arquivo */
                    System.out.print("Digite o nome do arquivo: ");
                    String fileName = scanner.nextLine();
                    fileName = scanner.nextLine();
                    Escrever("GetFile");
                    Escrever(fileName);

                    msgm = input.readLine();
                    msgm = enc.decrypt(msgm);
                    if((msgm.compareTo("FileFound"))==0){

                        System.out.println("Arquivo encontrado nos usuarios:");

                        /* Get Owners */
                        long ini = System.nanoTime();
                        msgm = input.readLine();
                        msgm = enc.decrypt(msgm);
                        String[] parts = msgm.split("_");
                        for(int i=0;i<parts.length;i++){
                            System.out.println(parts[i]);
                        }
                        Escrever(parts[0]);
                        msgm = input.readLine();
                        msgm = enc.decrypt(msgm);
                        System.out.println("Endereco: "+msgm);

                        if((msgm.compareTo("AddressNotFound"))!=0){

                            parts = msgm.split("_");
                            msgm = parts[0];
                            int port_server = Integer.parseInt(parts[1]);

                            parts = msgm.split("/");
                            msgm = parts[1];
                            parts = msgm.split(":");
                            msgm = parts[0];
                            System.out.println("Endereco formatado: "+msgm+" Porta: "+port_server);
                            Socket direct = new Socket(msgm, port_server);
                            long fim = System.nanoTime();
                            System.out.println("Conectado com "+msgm + "com um tempo de " + (fim-ini));
							ini = System.nanoTime();
                            BufferedWriter writer_direct = new BufferedWriter(new OutputStreamWriter(direct.getOutputStream()));
                            BufferedReader input_direct = new BufferedReader(new InputStreamReader(direct.getInputStream()));

                            fileName = enc.encrypt(fileName);
                            writer_direct.write(fileName);
                            writer_direct.newLine();
                            writer_direct.flush();
                            fileName = enc.decrypt(fileName);
                            Transfer(direct, fileName, writer_direct, input_direct);
							fim = System.nanoTime();
							System.out.println("tempo de envio do arquivo: " + (fim-ini));
                        }
                        else
                            System.out.println("Endereco nao encontrado ");
                    }


                }
                else if(op==4){
                    Escrever("AddFile");
                    System.out.print("\nDigite o nome do arquivo: ");
                    String fileName = scanner.nextLine();
                    fileName = scanner.nextLine();
                    while(!CheckName(fileName)){
                        System.out.print("\nNome do arquivo invalido");
                        System.out.print("\nDigite o nome do arquivo: ");
                        fileName = scanner.nextLine();
                    }
                    Escrever(fileName);
                    System.out.println("Requisicao enviada para o servidor");
                }
                else if(op==5){
                    Escrever("UpdateFiles");
                }
                else if(op==6){

                    Escrever("RemoveFile");
                    System.out.print("\nDigite o nome do arquivo: ");
                    String fileName = scanner.nextLine();
                    fileName = scanner.nextLine();
                    Escrever(fileName);
                    System.out.println("Requisicao enviada para o servidor");

                }
                else if(op==7){
                    System.out.println("Falows");
                    System.exit(0);
                }

                else
                    System.out.println("Opcao desconhecida");

            }catch(Exception e){e.printStackTrace();}
        }
    }

    /* Funcao que retorna False se a String tiver _ */

    public boolean CheckName(String fileName){
        if(fileName.length()==0)
            return false;
        for(int i=0;i<fileName.length();i++)
            if(fileName.charAt(i)=='_') return false;
        return true;
    }

    public void Transfer(Socket direct, String fileName, BufferedWriter writer_direct, BufferedReader input_direct){

        try{

            /* Receive fileSize */
            String fileSize = input_direct.readLine();
            fileSize = enc.decrypt(fileSize);
            String[] parts = fileSize.split("_");
            int size = Integer.parseInt(parts[1]);
            System.out.println("File size: "+size);

            /* Logo apos mandar o tamanho, o outro usuario ira mandar o arquivo */
            DataInputStream dis = new DataInputStream(direct.getInputStream());

            FileOutputStream fos = new FileOutputStream("./files/"+fileName);

            int bytes=0;

            for(int i=0;i<size;i++){
                bytes  = dis.read();
                fos.write(bytes);
            }

            fos.flush();
            fos.close();

            System.out.println("Received");

        }catch(Exception e){e.printStackTrace();}
    }

    public static void main(String[] args){
        new Client();
    }

}
